package leafedbox.managers
{
	import mx.formatters.CurrencyFormatter;
	import mx.formatters.DateFormatter;
	import mx.formatters.NumberFormatter;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;

	/**
	 * This class controls the formatting of data types.
	 */
	public class LocaleManagerImpl extends EventDispatcher
	{
		//------------------------------------------------------------------------------
		// Constructor
		//------------------------------------------------------------------------------
		
		/**
		 * Constructor.
		 */
		public function LocaleManagerImpl():void
		{
			// Initialize formatters
			numberFormatter = new NumberFormatter();

			currencyFormatter = new CurrencyFormatter();
            currencyFormatter.currencySymbol = "$"; // text('_currency');
            currencyFormatter.useThousandsSeparator = true;
            currencyFormatter.precision             = 2;

			durationFormatter = new NumberFormatter();
            durationFormatter.useThousandsSeparator = true;
            durationFormatter.precision             = 0;
            
			dateTimeFormatter  = new DateFormatter();
			dateFormatter      = new DateFormatter();
			shortDateFormatter = new DateFormatter();
			monthFormatter     = new DateFormatter();
			timeFormatter      = new DateFormatter();
			
			// Add listeners
			addEventListener("languageChange", onLanguageChange);
			
			// Initialize
			updateFormatters();
		}
		

		//------------------------------------------------------------------------------
		// Properties
		//------------------------------------------------------------------------------
		
		//----------------------------------
		// Strings
		//----------------------------------

		protected var localeStrings : Dictionary = new Dictionary();
		

		//----------------------------------
		// Formatters
		//----------------------------------

		/**
		 * @private
		 */
		protected var numberFormatter : NumberFormatter;
		
		/**
		 * @private
		 */
		protected var durationFormatter : NumberFormatter;
		
		/**
		 * @private
		 */
		protected var currencyFormatter : CurrencyFormatter;
		
		/**
		 * @private
		 */
		protected var dateTimeFormatter : DateFormatter;

		/**
		 * @private
		 */
		protected var dateFormatter : DateFormatter;

		/**
		 * @private
		 */
		protected var shortDateFormatter : DateFormatter;

		/**
		 * @private
		 */
		protected var monthFormatter : DateFormatter;

		/**
		 * @private
		 */
		protected var timeFormatter : DateFormatter;


		//------------------------------------------------------------------------------
		// Methods
		//------------------------------------------------------------------------------

		//----------------------------------
		// Locale text
		//----------------------------------
		
		/**
		 * Returns a locale-specific string based on the string code.
		 */
		[Bindable(event="languageChange")]
		public static function text(code:String):String
		{
		    return "";
		}


		//----------------------------------
		// Formatting
		//----------------------------------
		
		/**
		 * @private
		 * Updates the formatters by locale.
		 */
		protected function updateFormatters():void
		{
			dateTimeFormatter.formatString  = "MM/DD/YYYY KK:NN:SS A"; // text("_dtformat");    
			dateFormatter.formatString      = "EEEE MM/DD/YYYY"; // text("_dformat");    
			shortDateFormatter.formatString = "MM/DD/YYYY"; // text("_dformat");    
			monthFormatter.formatString     = "MMMM YYYY"; //text("_mformat");    
			timeFormatter.formatString      = "KK/NN/SS A"; // text("_tformat");    
		}
	
		/**
		 * @private
		 */
		public function formatNumber(value:Number, precision:int, useThousandsSeparator:Boolean):String
		{
			if(isNaN(value) || value == Infinity) {
            	return "";
            } else {
	            numberFormatter.precision             = precision;
	            numberFormatter.useThousandsSeparator = useThousandsSeparator;
				return numberFormatter.format(value);
			}
		}
		
		/**
		 * @private
		 */
		public function formatInt(value:int, useThousandsSeparator:Boolean):String
		{
			return formatNumber(value, 0, useThousandsSeparator);
		}
		
		/**
		 * @private
		 */
		public function formatCurrency(value:Number, precision:int, useThousandsSeparator:Boolean):String
		{
			if(isNaN(value) || value == Infinity) {
            	return "";
            } else {
	            currencyFormatter.precision             = precision;
	            currencyFormatter.useThousandsSeparator = useThousandsSeparator;
				return currencyFormatter.format(value);
			}
		}
		
		/**
		 * @private
		 */
		public function formatBoolean(value:*):String
		{
            if(value == 0 || value == false) {
            	return text("false");
            } else {
            	return text("true");
            }
		}
		
		/**
		 * @private
		 */
		public function formatPercent(value:Number, precision:int, useThousandsSeparator:Boolean):String
		{
			if(isNaN(value) || value == Infinity) {
            	return "";
            } else {
            	return (value * 100 > 0 && value * 100 < 1 ? "0" : "") + formatNumber(value * 100, precision, useThousandsSeparator) + "%";
            }
		}
		
		/**
		 * @private
		 * NOTE: Duration is assumed to be in seconds.
		 */
		public function formatDuration(value:int):String
		{
			var days      : int = value / 86400;
			var remainder : int = value % 86400;
			var hours     : int = remainder / 3600;
			remainder = remainder % 3600;

			var minutes   : int = remainder / 60;
			var seconds   : int = remainder % 60;

			var ret: String = (days > 0 ? durationFormatter.format(days) + "d " : "")
							+ (hours < 10 ? "0" : "") + hours + ":"
							+ (minutes < 10 ? "0" : "") + minutes + ":"
							+ (seconds < 10 ? "0" : "") + seconds;

			return ret;
		}
		
		/**
		 * @private
		 */
		public function formatDateTime(value:Date):String
		{
			return (value ? dateTimeFormatter.format(value) : "");
		}

		/**
		 * @private
		 */
		public function formatDate(value:Date):String
		{
			return (value ? dateFormatter.format(value) : "");
		}

		/**
		 * @private
		 */
		public function formatShortDate(value:Date):String
		{
			return (value ? shortDateFormatter.format(value) : "");
		}

		/**
		 * @private
		 */
		public function formatMonth(value:Date):String
		{
			return (value ? monthFormatter.format(value) : "");
		}

		/**
		 * @private
		 */
		public function formatTime(value:Date):String
		{
			return (value ? timeFormatter.format(value) : "");
		}

		
		//------------------------------------------------------------------------------
		// Events
		//------------------------------------------------------------------------------

		/**
		 * @private
		 */
		protected function onLanguageChange(event:Event):void
		{
			updateFormatters();
		}
	}
}